package com.codefish.framework.spring.beans.factory.config;

import com.codefish.framework.spring.beans.exception.BeansException;
import com.codefish.framework.spring.beans.factory.support.BeanDefinition;
import com.codefish.framework.spring.beans.factory.support.PropertyValue;

import java.util.List;

/**
 * {@link IBeanPostProcessor}接口的子接口，在其基础上增加了以下bean生命周期的钩子方法
 * <ol>
 *     <li>在bean被实例化之前</li>
 *     <li>在bean在实例化之后，设置属性之前</li>
 *     <li>在bean使用对应的{@link BeanDefinition#propertyValues}来进行属性赋值之前</li>
 * </ol>
 *
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/11/08 上午 09:20
 */
public interface IInstantiationAwareBeanPostProcessor extends IBeanPostProcessor {

    /**
     * <p>
     * 在bean被实例化之前调用，返回的对象(一般为代理对象)如果不为{@code null}，那么bean跳过使用
     * 默认的构造方法创建而使用这个返回的代理对象。
     * </p>
     * <p>
     * 默认实现下该方法返回{@code null}
     * </p>
     *
     * @param beanClass 待创建的bean实例的class对象
     * @param beanName  待创建的bean的名称
     * @return 返回一个代理对象来跳过构造方法创建bean实例，如果为{@code null}则仍然使用构造方法创建bean
     * @throws BeansException 发生异常时抛出
     */
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * <p>在bean被实例化后，设置属性前调用，一般用于实现对bean的依赖注入,返回值为布尔类型，表示后续的{@link IInstantiationAwareBeanPostProcessor}
     * 的{@link #postProcessAfterInitialization}方法是否还需要被执行。也就是说，如果返回false，那么后续的{@link #postProcessAfterInitialization}方法会被跳过执行。</p>
     * <p>默认实现下方法返回{@code true}</p>
     *
     * @param bean     完成实例化但未完成属性设置的bean实例
     * @param beanName bean实例对应的bean名称
     * @return 如果返回true，那么后续{@link #postProcessAfterInitialization}方法仍然执行，否则跳过后续所有方法。
     * @throws BeansException 发生异常时抛出
     */
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    /**
     * <p>对bean对应的{@link BeanDefinition#propertyValues}进行一些处理，返回真正需要使用的{@code propertyValues}</p>
     * <p>默认实现下其返回null</p>
     *
     * @param propertyValues 进行处理前的propertyValues
     * @param bean           准备使用propertyValues进行属性赋值的bean实例
     * @param beanName       bean实例对应的bean的名称
     * @return 返回处理后的propertyValues，如果返回null则使用使用上次处理结果来对bean进行属性赋值
     * @throws BeansException 发生异常时抛出
     */
    default List<PropertyValue> postProcessPropertyValues(List<PropertyValue> propertyValues, Object bean, String beanName) throws BeansException {
        return null;
    }
}
